﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Crm.Sdk.Samples;

namespace WorkflowAutomation
{
    class Program
    {
        static void Main(string[] args)
        {            
			LogHelper.LogMessage("---- Application started ------------");

			try
			{

				//retrieve the CRM server connection details from the config file.
				ServerConnection serverConnection = new ServerConnection();
				ServerConnection.Configuration serverConfig = serverConnection.GetServerConfiguration();

				OrganizationServiceProxy _serviceProxy;
				using (_serviceProxy = new OrganizationServiceProxy(serverConfig.OrganizationUri,
																		serverConfig.HomeRealmUri,
																		serverConfig.Credentials,
																		serverConfig.DeviceCredentials))
				{
					//read the workflow details from the configuraiton file
					List<WorkflowDetails> workflowConfigs = WorkflowDetails.GetWorkflowDetails();

					LogHelper.LogMessage("Workflow configuration found: " + workflowConfigs.Count.ToString());

					for (int i = 0; i < workflowConfigs.Count; i++)
					{
                        if (workflowConfigs[i].Enabled)
                        {
                            //retrieve details about the workflow from server.
                            ColumnSet cols = new ColumnSet(new string[] { "name", "primaryentity" });
                            Entity workflow = _serviceProxy.Retrieve("workflow", workflowConfigs[i].WorkflowGUID, cols);

                            workflowConfigs[i].PrimaryEntity = workflow.GetAttributeValue<string>("primaryentity");
                            workflowConfigs[i].WorkflowName = workflow.GetAttributeValue<string>("name");

                            //execute workflow.
                            ExecuteWorkflow(_serviceProxy, workflowConfigs[i]);
                        }
					}
				}
			}
			catch (Exception ex)
			{
				LogHelper.LogErrorMessage("Error occurred: ", ex);
			}

			LogHelper.LogMessage("---- Application ended ------------");
		}

		private static void ExecuteWorkflow(OrganizationServiceProxy _serviceProxy, WorkflowDetails workflowDetails)
		{
			LogHelper.LogMessage("Executing workflow: " + workflowDetails.WorkflowName);
			int recordProcessed = 0;

			try
			{
				//convert the FetchXML to Query.
				FetchXmlToQueryExpressionRequest fetchToQueryReq = new FetchXmlToQueryExpressionRequest();
				fetchToQueryReq.FetchXml = workflowDetails.FetchXML;
				FetchXmlToQueryExpressionResponse fetchToQueryResp = _serviceProxy.Execute(fetchToQueryReq) as FetchXmlToQueryExpressionResponse;

				//set the paging details
				QueryExpression query = fetchToQueryResp.Query;
				//query.PageInfo = new PagingInfo();
				query.PageInfo.PageNumber = 1;
				query.PageInfo.Count = 200;

				//retrieve the records.
				EntityCollection entities;
				
				do
				{
					entities = _serviceProxy.RetrieveMultiple(query);
					if (entities != null && entities.Entities.Count > 0)
					{
						//execute the workflow against each of the record found.
						for (int x = 0; x < entities.Entities.Count; x++)
						{
							// Create an ExecuteWorkflow request.
							ExecuteWorkflowRequest request = new ExecuteWorkflowRequest()
							{
								WorkflowId = workflowDetails.WorkflowGUID,
								EntityId = entities.Entities[x].GetAttributeValue<Guid>(workflowDetails.PrimaryEntity + "id")
							};

							// Execute the workflow.
							ExecuteWorkflowResponse response = (ExecuteWorkflowResponse)_serviceProxy.Execute(request);
							recordProcessed += 1;
						}
					}

					//set the paging cookie to retrieve the next set of records.
					if (entities.MoreRecords)
					{
						query.PageInfo.PagingCookie = entities.PagingCookie;
						query.PageInfo.PageNumber += 1;
					}
				} while (entities != null && entities.MoreRecords);
			}
			catch (Exception ex)
			{
				LogHelper.LogErrorMessage("Error occurred: ", ex);
			}
			finally
			{
				LogHelper.LogMessage("-- " + workflowDetails.PrimaryEntity + " record processed: " + recordProcessed.ToString());
			}
		}
		
	}
}
